﻿using System.Web;
using DoNet.Helper;
using DoNet.Platform.Wechat.Model;

namespace DoNet.Platform.Wechat
{
    /// <summary>
    /// 微信Access Token
    /// </summary>
    public class TokenApi
    {
        /// <summary>
        /// 获取Access Token
        /// </summary>
        /// <param name="appid">公众号的唯一标识</param>
        /// <param name="secret">公众号的appsecret</param>
        /// <param name="code">用户授权后得到code </param>
        /// <returns></returns>
        public static ReturnData GetToken(string appid, string secret, string code)
        {
            /*
            参数	是否必须	说明
            appid	是	公众号的唯一标识
            secret	是	公众号的appsecret
            code	是	填写第一步获取的code参数
            grant_type	是	填写为authorization_code

            https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code

            参数	描述
            access_token	网页授权接口调用凭证,注意：此access_token与基础支持的access_token不同
            expires_in	access_token接口调用凭证超时时间，单位（秒）
            refresh_token	用户刷新access_token
            openid	用户唯一标识，请注意，在未关注公众号时，用户访问公众号的网页，也会产生一个用户和公众号唯一的OpenID
            scope	用户授权的作用域，使用逗号（,）分隔
            is_snapshotuser	是否为快照页模式虚拟账号，只有当用户是快照页模式虚拟账号时返回，值为1
            unionid	用户统一标识（针对一个微信开放平台账号下的应用，同一用户的 unionid 是唯一的），只有当scope为"snsapi_userinfo"时返回

            错误时微信会返回JSON数据包如下（示例为Code无效错误）:
            {"errcode":40029,"errmsg":"invalid code"}
            */

            string reqUrl = CommonConfig.WebApiUrl_Wechat_api + string.Format("/sns/oauth2/access_token?grant_type=authorization_code&appid={0}&secret={1}&code={2}", appid, secret, code);
            var result = HttpHelper.HttpGet(reqUrl);
            if (result.success)
            {
                var obj = JsonHelper.DeserializeObject<dynamic>(result.data);
                if (obj != null)
                {
                    /*
                    {
                        "errcode":40029,
                        "errmsg":"invalid code"
                    }
                    */
                    if (obj.errcode != null)
                    {
                        return new ReturnData()
                        {
                            success = false,
                            message = obj.errmsg,
                            data = result.data
                        };
                    }
                    else
                    {
                        return result;
                    }
                }
                else
                {
                    return result;
                }
            }
            else
            {
                return result;
            }
        }

        /// <summary>
        /// 获取授权URL
        /// </summary>
        /// <param name="appid">公众号的唯一标识（这个就是我们前面申请的）</param>
        /// <param name="redirect_uri">授权后重定向的回调链接地址（我们前面申请的）</param>
        /// <param name="scope">应用授权作用域，snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），snsapi_userinfo （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且，即使在未关注的情况下，只要用户授权，也能获取其信息）</param>
        /// <param name="state">重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值，最多128字节，该值会被微信原样返回，我们可以将其进行比对，防止别人的攻击。</param>
        /// <returns></returns>
        public static string GetAuthorizeUrl(string appid, string redirect_uri, string scope, string state = "")
        {
            /*
            参数	是否必须	说明
            appid	是	公众号的唯一标识
            redirect_uri	是	授权后重定向的回调链接地址， 请使用 urlEncode 对链接进行处理
            response_type	是	返回类型，请填写code
            scope	是	应用授权作用域，snsapi_base （不弹出授权页面，直接跳转，只能获取用户openid），snsapi_userinfo （弹出授权页面，可通过openid拿到昵称、性别、所在地。并且， 即使在未关注的情况下，只要用户授权，也能获取其信息 ）
            state	否	重定向后会带上state参数，开发者可以填写a-zA-Z0-9的参数值，最多128字节
            #wechat_redirect	是	无论直接打开还是做页面302重定向时候，必须带此参数
            forcePopup	否	强制此次授权需要用户弹窗确认；默认为false；需要注意的是，若用户命中了特殊场景下的静默授权逻辑，则此参数不生效
            return "https://open.weixin.qq.com/connect/oauth2/authorize?response_type=code&appid={0}&redirect_uri={1}&scope=snsapi_base&state={2}#wechat_redirect";
            */
            string param = string.Format("/connect/oauth2/authorize?response_type=code&appid={0}&redirect_uri={1}&scope={2}", appid, HttpUtility.UrlEncode(redirect_uri), scope);
            if(!string.IsNullOrWhiteSpace(state))
            {
                param += string.Format("&state={0}", state);
            }
            return CommonConfig.WebApiUrl_Wechat_open + param + "#wechat_redirect";
        }

        /// <summary>
        /// 根据openId获取用户信息
        /// 根据openId获取用户昵称等信息，openid可通过授权获取
        /// </summary>
        /// <param name="access_token">采用OAuth授权方式为必填参数</param>
        /// <param name="openId">用户标识（openId）</param>
        /// <returns></returns>
        public static ReturnData GetUserInfo(string access_token, string openId)
        {
            string reqUrl = CommonConfig.WebApiUrl_Wechat_api + string.Format("/sns/userinfo?access_token={0}&openid={1}", access_token, openId);
            var result = HttpHelper.HttpGet(reqUrl);

            if (result.success)
            {
                var obj = JsonHelper.DeserializeObject<dynamic>(result.data);
                if (obj != null)
                {
                    /*
                    {
                        "errcode":40029,
                        "errmsg":"invalid code"
                    }
                    */
                    if (obj.errcode != null)
                    {
                        return new ReturnData()
                        {
                            success = false,
                            message = obj.errmsg,
                            data = result.data
                        };
                    }
                    else
                    {
                        return result;
                    }
                }
                else
                {
                    return result;
                }
            }
            return result;
        }
    }
}
